/*
 * =====================================================================================
 *
 *       Filename:  Bitmap.c
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  10/29/2013 01:11:06 PM
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Robert (), 1198023575@qq.com
 *   Organization:  DaLian JiaoTong University
 *
 * =====================================================================================
 */

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include "Bitmap.h"


int bitmap_init(Bitmap* bitmap, char* filename)
{
	int fd = open(filename, O_RDONLY);
	if(fd < 0) {
		fprintf(stderr, "Can't open %s in %s\n", filename, __FUNCTION__);
		return -1;
	}

	bitmap->header = malloc(sizeof(BitmapHeader));
	if(bitmap->header == NULL) {
		fprintf(stderr, "Error in alloc bitmap header!\n");
		return -2;
	}
	bzero(bitmap->header, sizeof(BitmapHeader));
	if(sizeof(BitmapHeader) != read(fd, bitmap->header, sizeof(BitmapHeader))) {
		fprintf(stderr, "Error in read bitmap header\n");
		close(fd);
		return -3;
	}

	bitmap->xres = bitmap->header->info_header.biWidth;
	/*
	 * 因为位图文件的宽度必须为4的整数倍，当数据宽度不是4的整数倍时
	 * 填充0
	 */
	int extra = 0;
	int xbytes = bitmap->xres*bitmap->header->info_header.biBitsPerPixel/8;
	while(xbytes % 4 != 0) {
		xbytes++;
		extra++;
	}
	bitmap->extra = extra;

	bitmap->yres = bitmap->header->info_header.biHeight;

	bitmap->bits_per_pixel = bitmap->header->info_header.biBitsPerPixel;

	bitmap->data = malloc(bitmap->header->info_header.biImageSize);
	if(bitmap->data == NULL) {
		fprintf(stderr, "Error in malloc bitmap\n");
		close(fd);
		return -4;
	}
	// begin change
    lseek(fd, bitmap->header->file_header.bfOffBits, SEEK_SET);
		// end change
	if(bitmap->header->info_header.biImageSize !=
			read(fd, bitmap->data, bitmap->header->info_header.biImageSize)) {
		fprintf(stderr, "Error in read bitmap data to Bitmap struct\n");
		free(bitmap->data);
		close(fd);
		return -5;
	}

	close(fd);
	return 0;
}


void bitmap_destroy(Bitmap* bitmap)
{
	free(bitmap->data);
	free(bitmap->header);
	memset(bitmap, '\0', sizeof(Bitmap));
}

void print_file_header(BitmapFileHeader* header)
{
	printf("bfType: %c%c\n", *(char*)(&header->bfType), *(((char*)&header->bfType)+1));
	printf("bfSize: %d\n", header->bfSize);
	printf("bfReserved1: %d\n", header->bfReserved1);
	printf("bfReserved2: %d\n", header->bfReserved2);
	printf("bfOffBits: %d\n", header->bfOffBits);
}

void print_info_header(BitmapInfoHeader* header)
{
	printf("biSize: %d\n", header->biSize);
	printf("biWidth: %d\n", header->biWidth);
	printf("biHeight: %d\n", header->biHeight);
	printf("biPlanes: %d\n", header->biPlanes);
	printf("biBitsPerPixel: %d\n", header->biBitsPerPixel);
	printf("biCompression: %d\n", header->biCompression);
	printf("biImageSize: %d\n", header->biImageSize);
	printf("biXPixelsPerMeter: %d\n", header->biXPixelsPerMeter);
	printf("biYPixelsPerMeter: %d\n", header->biYPixelsPerMeter);
	printf("biClrUsed: %d\n", header->biClrUsed);
	printf("biClrImportant: %d\n", header->biClrImportant);
}
void bitmap_info(Bitmap* bitmap)
{
	/*
	   BitmapHeader *bitmap_header;
	   typedef struct BitmapHeader {
	   BitmapFileHeader file_header;
	   BitmapInfoHeader info_header;
	   } BitmapHeader;
	   */
	print_file_header(&(bitmap->header->file_header));
	print_info_header(&(bitmap->header->info_header));
}
